package intention;

import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import javax.swing.SpringLayout;
import javax.swing.border.*;
import java.net.URL;
import java.awt.*;
import java.util.Date;
import java.text.DecimalFormat;

public class IntentionView extends FrameView {

    //components
    private javax.swing.JFrame mainFrame;
    private ImagePanel mainPanel;
    private javax.swing.JLabel qLabel1, qLabel2;
    private javax.swing.JTextField aField1;
    public javax.swing.JSpinner aField2;
    public javax.swing.JButton startButton;
    private java.awt.Font standardFont;
    private FlickrGrabber fg;
    final private SystemTray tray = SystemTray.getSystemTray();
    public TrayIcon trayIcon;
    public long startTime;

    //return intention time in milliseconds
    public int getTime() {
        return Integer.decode(aField2.getValue().toString()) * 60 * 1000;
    }

    public String getIntention() {
        return aField1.getText();
    }

    public IntentionView(SingleFrameApplication app) {
        super(app);

        //Layout the frame components
        initComponents();

        //Expand to 100% screen size
        expandFullScreen();

        //Active always-on-top
        initOnTop();

        //Create Tray Icon
        initTray();
    }

    private void initComponents() {
        //instantiate components
        fg = new FlickrGrabber();
        mainFrame = this.getFrame();
        mainFrame.setTitle("Intention");
        mainPanel = new ImagePanel(fg.grabInterestingImage());
        qLabel1 = new javax.swing.JLabel(); //Question 1 - intention
        qLabel2 = new javax.swing.JLabel(); //Question 2 - time
        aField1 = new javax.swing.JTextField();
        aField2 = new javax.swing.JSpinner();
        startButton = new javax.swing.JButton("Begin");
        standardFont = new java.awt.Font(Font.SANS_SERIF, Font.BOLD, 18);

        //name components (for listeners) using setName
        //--not currently necessary

        //Frame layout, spring-layout
        mainFrame.setContentPane(mainPanel);
        SpringLayout sLayout = new SpringLayout();
        mainPanel.setLayout(sLayout);

        //Set tab/enter order
        aField1.setFocusTraversalKeysEnabled(true);
        aField2.setFocusTraversalKeysEnabled(true);

        //combine and add components
        qLabel1.setText("What do you intend to do?");
        qLabel1.setBackground(Color.lightGray);
        qLabel1.setOpaque(true);
        qLabel1.setFont(standardFont);
        //qLabel1.setBorder(new EmptyBorder(1,3,1,3));
        qLabel1.setBorder(new BevelBorder(BevelBorder.LOWERED));
        mainPanel.add(qLabel1);
        mainPanel.add(aField1);
        //aField1.setLineWrap(true);
        //aField1.setWrapStyleWord(true);
        qLabel2.setText("How long will that take (in minutes)?");
        qLabel2.setBackground(Color.lightGray);
        qLabel2.setOpaque(true);
        //qLabel2.setBorder(new EmptyBorder(1,3,1,3));
        qLabel2.setBorder(new BevelBorder(BevelBorder.LOWERED));
        mainPanel.add(qLabel2);
        mainPanel.add(aField2);
        mainPanel.add(startButton);

        //Assign fonts for each component
        Component[] panelComps = mainPanel.getComponents();
        for (Component comp : panelComps) {
            comp.setFont(standardFont);
        }

        //determine layout constraints
        // reminder: SIDE, component, distance, SIDE, anchor (distance may also be a spring)
        //Horizontal specifications
        sLayout.putConstraint(SpringLayout.WEST, qLabel1, -200, SpringLayout.HORIZONTAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.WEST, aField1, -200, SpringLayout.HORIZONTAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.EAST, aField1, 200, SpringLayout.HORIZONTAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.WEST, qLabel2, -200, SpringLayout.HORIZONTAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.WEST, aField2, -200, SpringLayout.HORIZONTAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.EAST, aField2, -10, SpringLayout.WEST, startButton);
        sLayout.putConstraint(SpringLayout.WEST, startButton, -120, SpringLayout.HORIZONTAL_CENTER, mainPanel);

        //Vertical specifications
        int spacing = 35;
        sLayout.putConstraint(SpringLayout.NORTH, qLabel1, -2 * spacing, SpringLayout.VERTICAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.NORTH, aField1, -1 * spacing, SpringLayout.VERTICAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.SOUTH, aField1, -10, SpringLayout.NORTH, qLabel2);
        sLayout.putConstraint(SpringLayout.NORTH, qLabel2, 1 * spacing, SpringLayout.VERTICAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.NORTH, aField2, 2 * spacing, SpringLayout.VERTICAL_CENTER, mainPanel);
        sLayout.putConstraint(SpringLayout.NORTH, startButton, 2 * spacing, SpringLayout.VERTICAL_CENTER, mainPanel);
    }

    private void expandFullScreen() {
        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        tryExpansion(gd, mainFrame);
    }

    private void tryExpansion(GraphicsDevice gd, Frame mainFrame) {
        if (gd.isFullScreenSupported()) {
            mainFrame.setUndecorated(true); //not necessary?
            mainFrame.setResizable(false); //For some reason, this makes it fill the whole screen instead of the packed dimensions. WTF?
            gd.setFullScreenWindow(this.getFrame());
        } else {
            System.err.println("Full screen not supported");
            mainFrame.setSize(800, 600);
            mainFrame.setVisible(true);
        }
    }

    private void initOnTop() {
        mainFrame.setAlwaysOnTop(true);
    }

    private void initTray() {
        if (!SystemTray.isSupported()) {
            System.out.println("SystemTray not available.");
            return;
        }

        //create and populate the pop up menu
        final PopupMenu popMenu = new PopupMenu();
        MenuItem menuFinished = new MenuItem("Finished");
        popMenu.add(menuFinished);

        //create and add the tray icon
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        URL url = getClass().getResource("images/elephant-large.png");
        Image elephantIcon = toolkit.getImage(url);
        trayIcon = new TrayIcon(elephantIcon , "Intention", popMenu);
        trayIcon.setImageAutoSize(true);

        try {
            tray.add(trayIcon);

        } /*
        NullPointerException - if trayIcon is null
        IllegalArgumentException - if the same instance of a TrayIcon is added more than once
        AWTException - if the desktop system tray is missing
         */ catch (AWTException a) {
            System.out.println("System Tray not programmatically accessible.");
            System.exit(0);
        } catch (IllegalArgumentException i) {
            System.out.println("System Tray icon is already in place.");
            System.exit(0);
        } catch (NullPointerException n) {
            System.out.println("System Tray icon is null.");
            System.exit(0);
        }
    }

    public void minToTray() {
        mainFrame.setVisible(false);
    }

    public void triggerWarning(int minutes) {
        String warningMessage = "You only intended to "
                + getIntention() + " for " + minutes
                + " more minutes. Please save your work now.";
        //Trigger generic tray icon pop up
        trayIcon.displayMessage("Intention", warningMessage, TrayIcon.MessageType.INFO);
    }

    public void triggerEnd() {
      complete();
        //<<TBD>> a dialog telling the user that their time is up. Enter another intention to continue, but be honest. Also, now would be a great time to stretch, grab a bite, take a walk, or talk to someone.
    }

    public void triggerFinished() {
       complete();
        //<<TBD>> a dialog telling the user that they ended early.
    }

    private void complete()
    {
        mainPanel.updateImage(fg.grabInterestingImage());
        mainFrame.setVisible(true);
    }

    public void showTimeLeft() {
        Long now = new Date().getTime();
        Long passed = now - startTime;
        int left = getTime() - Integer.valueOf(passed.toString()); //time left in milliseconds
        int second = 1000;
        int minute = 60 * second;
        int hour = 60 * minute;
        int hours = (left - left % hour) / hour;
        int minutes = (left - left % minute) / minute - hours * 60;
        int seconds = ((left - left % second) / second) - hours * 60 * 60 - minutes * 60;
        DecimalFormat df = new DecimalFormat("00");
        String timeMessage = "" + df.format(hours) + ":" + df.format(minutes) + ":" + df.format(seconds) + " remaining.";
        trayIcon.setToolTip(timeMessage);
    }
}
